/**
 * 
 */
package cn.springsoter.core.tool.utils;

import java.text.ParseException;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.exception.ExceptionUtils;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.i18n.phonenumbers.AsYouTypeFormatter;
import com.google.i18n.phonenumbers.NumberParseException;
import com.google.i18n.phonenumbers.PhoneNumberToCarrierMapper;
import com.google.i18n.phonenumbers.PhoneNumberUtil;
import com.google.i18n.phonenumbers.PhoneNumberUtil.PhoneNumberFormat;
import com.google.i18n.phonenumbers.Phonenumber.PhoneNumber;
import com.google.i18n.phonenumbers.geocoding.PhoneNumberOfflineGeocoder;

import cn.springsoter.core.tool.constant.SpringSoterConstant;
import cn.springsoter.core.tool.exception.ServiceException;
import cn.springsoter.core.tool.model.vo.RegionCodeVO;
import lombok.extern.slf4j.Slf4j;



/**
 * 电话工具类
 * @author kevin
 *
 */
@Slf4j
public class PhoneUtil {
	private static PhoneNumberUtil phoneNumberUtil = PhoneNumberUtil.getInstance();
	 
    private static PhoneNumberToCarrierMapper carrierMapper = PhoneNumberToCarrierMapper.getInstance();
 
    private static PhoneNumberOfflineGeocoder geocoder = PhoneNumberOfflineGeocoder.getInstance();
 
    private PhoneUtil() {}
    
    /**
     * 根据国家代码和手机号  判断手机号是否有效
     * @param phone
     * @param countryCode
     * @return
     */
    public static boolean isValidNumber(PhoneNumber phoneNumber){
        return phoneNumberUtil.isValidNumber(phoneNumber);
    }
 
    /**
     * 根据国家代码和手机号  判断手机运营商
     * @param phone
     * @param countryCode
     * @return
     */
    public static String getCarrier(PhoneNumber phoneNumber){
        //返回结果只有英文，自己转成成中文
        String carrierEn = carrierMapper.getNameForNumber(phoneNumber, Locale.ENGLISH);
        String carrierZh = "";
        carrierZh += geocoder.getDescriptionForNumber(phoneNumber, Locale.CHINESE);
        switch (carrierEn) {
        case "China Mobile":
            carrierZh += "移动";
            break;
        case "China Unicom":
            carrierZh += "联通";
            break;
        case "China Telecom":
            carrierZh += "电信";
            break;
        default:
            break;
        }
        return carrierZh;
    }
 
 
    /**
     * 
    * @Description: 根据国家代码和手机号  手机归属地
    * @param @param phone
    * @param @param countryCode
    * @param @return    参数
    * @throws
     */
    public static String getGeo(PhoneNumber phoneNumber){
        return geocoder.getDescriptionForNumber(phoneNumber, Locale.CHINESE);
    }
    
    /**
     * 根据手机号和国家代号获取PhoneNumber对象
     * 
     * @param phone		手机号[可以带区号]，比如：+8613666668888
     * @param region	国家代码，默认是CN，具体参考：https://www.iso.org/obp/ui/#search
     * @return
     */
    public static PhoneNumber getPhoneNumber(String phone, String region) {
    	try {
			PhoneNumber phoneNumber = phoneNumberUtil.parse(phone, StringUtils.defaultString(region, "CN"));
			return phoneNumber;
		} catch (NumberParseException e) {
			log.error(ExceptionUtils.getStackTrace(e));
		}
    	return null;
    }
    
    /**
     * 获取带区号的手机号
     * 
     * @param phone
     * @param region
     * @return
     * @throws CityException
     */
    public static String getFullPhoneNumber(String phone, String region) throws ServiceException{
    	PhoneNumber phoneNumber = getPhoneNumber(phone, region);
    	if(Objects.isNull(phoneNumber) || !PhoneUtil.isValidNumber(phoneNumber)) {
    		log.error("输入的手机号码格式不正确：{}，region：{}，phoneNumber：{}", phone, region, phoneNumber);
    		throw new ServiceException(SpringSoterConstant.INVALID_PHONE_NUMBER);
    	}
    	return phoneNumberUtil.format(phoneNumber, PhoneNumberFormat.E164);
    }
    
    /**
     * 获取所有国家的区域代码
     * 
     * @return
     */
    public static List<RegionCodeVO> getRegionCodeMap(){
    	PhoneNumberUtil phoneUtil = PhoneNumberUtil.getInstance();
    	Set<String> regionSet = phoneUtil.getSupportedRegions();
    	List<RegionCodeVO> list = Lists.newArrayList();
		regionSet.forEach(region -> {
			int code = phoneUtil.getCountryCodeForRegion(region);
			RegionCodeVO vo = new RegionCodeVO(region, "+"+code);
			list.add(vo);
		});
		return list;
    }
}
